package com.brainhealth.web.controller.common;

import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.brainhealth.common.annotation.Anonymous;
import com.brainhealth.common.constant.CacheConstants;
import com.brainhealth.common.core.domain.AjaxResult;
import com.brainhealth.common.core.redis.RedisCache;
import com.brainhealth.common.utils.StringUtils;
import com.brainhealth.common.utils.http.HttpClientUtil;
import com.brainhealth.customer.domain.Customer;
import com.brainhealth.customer.service.ICustomerService;
import com.brainhealth.utils.CommonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Formatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/wxPublicAuth")
public class WechatController
{

    @Autowired
    ICustomerService customerService;
    @Autowired
    RedisCache redisCache;

    private static final Logger logger = LoggerFactory.getLogger(WechatController.class);

    private Long TICKET_TIMESTAMP;
    private String JSAPI_TICKET;
    public static String WXPUBLIC_APP_ID ="wx89289c3a3da01e68";
    // 公众号开发者秘钥
    private static final String WXPUBLIC_SECRET = "8dfe295275dbe4c3a0ee8de5d9840814";
    private static final String GETACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
    private static final String GETTICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";
//    public String WXPUBLIC_CALLBACK = "http://48d7df7d.r5.cpolar.top/wxPublicAuth/callback";

    //	回调方法
    @Anonymous
    @RequestMapping("/getOpenId")
    public AjaxResult wxCallBack(HttpServletRequest request, HttpServletResponse response)
    {
        Customer customer = CommonUtils.getCustomerByRequest(request);
        String code = request.getParameter("code");
        logger.info("获取到微信" + code);
        //获取access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?appid=" + WXPUBLIC_APP_ID + "&secret=" + WXPUBLIC_SECRET + "&code=" + code + "&grant_type=authorization_code";
        String tokenResult = HttpClientUtil.doGet(url);
        logger.info("请求获取access_token:" + tokenResult);
        //返回结果的json对象
        JSONObject resultObject = JSON.parseObject(tokenResult);//请求获取userInfo
        String openId = resultObject.getString("openid");
        if (!StringUtils.isNullOrEmpty(openId))
        {
            customer.setOpenId(openId);
            customerService.updateCustomerInfo(customer);
        }
//        String infoUrl = "https://api.weixin.qq.com/sns/userinfo" + "?access_token=" + resultObject.getString("access_token") + "&openid=" + resultObject.getString("openid") + "&lang=zh_CN";
//        String resultInfo = HttpClientUtil.doGet(infoUrl);
//        JSONObject userResult = JSONObject.parseObject(resultInfo);
//        //此时已获取到userInfo，再根据业务进行处理
//        logger.info("请求获取userInfo:" + resultInfo);
        return AjaxResult.success(customer);
    }

    /**
     * @return UniformResultTemplate<Map < String, String>>
     * @Description h5微信分享数据准备
     * @author cyy
     * @date 2021/2/12 21:16
     * @Param [url] 前端分享页面服务器路径（一定要前端获取分享页面地址，不要后端写死，写死容易造成签名错误问题出现）
     */
    @RequestMapping(value = "/getShareData")
    public AjaxResult getShareData(@RequestBody Map<String, String> map) throws IOException
    {
        String url = map.get("url");
        long currentTimestamp = System.currentTimeMillis() / 1000;
        logger.info("1、准备获取微信ticket"+ url);
        if ((StringUtils.isEmpty(JSAPI_TICKET) && TICKET_TIMESTAMP == null) || (StringUtils.isNotEmpty(JSAPI_TICKET) && TICKET_TIMESTAMP != null && TICKET_TIMESTAMP + 7200 < currentTimestamp))
        {
            logger.info("2、调用微信接口获取ticket");
            JSAPI_TICKET = getTicket(url);
            TICKET_TIMESTAMP = System.currentTimeMillis() / 1000;
        }
        logger.info("3、返回前端获取的ticket");
        Map<String, String> ret = sign(JSAPI_TICKET, url);
        JSAPI_TICKET = "";
        TICKET_TIMESTAMP = null;
        return AjaxResult.success(ret);
    }

    private String getTicket(String url)
    {
        String accessKey = redisCache.getCacheObject(CacheConstants.WECHAT_ACCESS_KEY);
        logger.info("获取缓存微信接口accessKey");
        if (StringUtils.isNullOrEmpty(accessKey))
        {
            // 获取“access_token”,建议放于缓存或者数据库中，定时刷新
            logger.error("参数url: {}", url);
            String getAccessTokenPath = GETACCESSTOKEN_URL.replace("APPID", WXPUBLIC_APP_ID).replace("APPSECRET", WXPUBLIC_SECRET);
            logger.error("参数getAccessTokenPath: {}", getAccessTokenPath);
            com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(HttpUtil.get(getAccessTokenPath));
            logger.error("参数jsonObject: {}", jsonObject);
            accessKey = jsonObject.getString("access_token");
            redisCache.setCacheObject(CacheConstants.WECHAT_ACCESS_KEY, accessKey, 2, TimeUnit.HOURS);
        }
        logger.error("参数access_token: {}", accessKey);
        // 根据“access_token”获取“jsapi_ticket”
        String getTicketPath = GETTICKET_URL.replace("ACCESS_TOKEN", accessKey);
        logger.error("参数getTicketPath: {}", getTicketPath);
        com.alibaba.fastjson.JSONObject jsonObject1 = JSON.parseObject(HttpUtil.get(getTicketPath));
        logger.error("参数jsonObject1: {}", jsonObject1);
        String ticket = jsonObject1.getString("ticket");
        logger.error("参数ticket: {}", ticket);
        return ticket;
    }

    public static Map<String, String> sign(String jsapi_ticket, String url)
    {
        Map<String, String> ret = new HashMap<>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写，且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" + nonce_str +
                "&timestamp=" + timestamp +
                "&url=" + url;

        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(string1.getBytes("UTF-8"));
            signature = byteToHex(crypt.digest());
        } catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("app_id", WXPUBLIC_APP_ID);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);

        return ret;
    }

    private static String create_nonce_str()
    {
        String uuid = UUID.randomUUID().toString().replace("-", "");
        return uuid.substring(0, 15).toUpperCase();
    }

    private static String create_timestamp()
    {
        return Long.toString(System.currentTimeMillis() / 1000);
    }

    private static String byteToHex(final byte[] hash)
    {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
}
